package org.xmap.storage;
import java.io.*;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.microedition.rms.*;
import org.xmap.ui.ViewManager;
class StoreItem {
    public int rmsId;
    public final int userData;
    // 所有子节点
    public final String subRmsName;
    public final int subRmsId;
    public StoreItem(int rmsId, String subRmsName, int subRmsId, int userData) {
        this.rmsId = rmsId;
        this.subRmsName = subRmsName;
        this.subRmsId = subRmsId;
        this.userData = userData;
    }
}
public class Storage {
    private RecordStore itemRs;
    private Hashtable subRms = new Hashtable(4);
    private Hashtable idMap = new Hashtable(8);
    private Hashtable userDataMap = new Hashtable(8);
    // 子rms创建规则,以下划线为开头(其它的rms不允许以下划线开头),然后是主rms的名字,然后是序号,序号从0开始
    public void open(String name) {
        if (this.itemRs == null && name != null) {
            try {
                this.itemRs = RecordStore.openRecordStore(name, true);
                RecordEnumeration re = this.itemRs.enumerateRecords(null, null, false);
                ViewManager.instance.debugPrint("打开RmsStore:" + name
                                                + ",记录数:" + this.itemRs.getNumRecords()
                                                + ",大小:" + this.itemRs.getSizeAvailable());
                // 查找子rms
                String[] allRms = RecordStore.listRecordStores();
                for (int i = 0; i < allRms.length; i++) {
                    if (allRms[i].startsWith("_" + name)) {
                        RecordStore subRs = RecordStore.openRecordStore(allRms[i], false);
                        ViewManager.instance.debugPrint("打开子Rms:" + allRms[i]
                                + ",记录数:" + subRs.getNumRecords()
                                + ",大小:" + subRs.getSizeAvailable());
                        this.subRms.put(allRms[i], subRs);
                    }
                }
                while (re.hasNextElement()) {
                    int rmsId = re.nextRecordId();
                    byte[] data = this.itemRs.getRecord(rmsId);
                    DataInputStream dis = new DataInputStream(new ByteArrayInputStream(data));
                    String rsName = dis.readUTF();
                    int subRmsId = dis.readInt();
                    int userData = dis.readInt();
                    // userId
                    // length
                    // node count
                    // count {
                    //         rmsNameIndex
                    //         rmsId;
                    // }
                    StoreItem si = new StoreItem(rmsId, rsName, subRmsId, userData);
                    this.idMap.put(new Integer(rmsId), si);
                    this.userDataMap.put(new Integer(userData), si);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    public int addRecord(int userData, byte[] data, int offset, int len) {
        if (this.itemRs == null) {
            return -1;
        }
        StoreItem si = (StoreItem)this.userDataMap.get(new Integer(userData));
        if (si != null) { // 目前不支持更新数据
            return si.rmsId;
        }
        try {
            Enumeration e = this.subRms.elements();
            while (e.hasMoreElements()) {
                RecordStore subRs = (RecordStore) e.nextElement();
                int sizeAvailable = subRs.getSizeAvailable();
                if (sizeAvailable > len) {
                    int subRmsId = subRs.addRecord(data, offset, len);
                    si = new StoreItem(0, subRs.getName(), subRmsId, userData);
                    ByteArrayOutputStream baos = new ByteArrayOutputStream(20);
                    DataOutputStream dos = new DataOutputStream(baos);
                    dos.writeUTF(si.subRmsName);
                    dos.writeInt(si.subRmsId);
                    dos.writeInt(si.userData);
                    byte[] itemData = baos.toByteArray();
                    try {
                        int rmsId = this.itemRs.addRecord(itemData, 0, itemData.length);
                        si.rmsId = rmsId;
                        this.idMap.put(new Integer(rmsId), si);
                        this.userDataMap.put(new Integer(userData), si);
                        return rmsId;
                    } catch (RecordStoreFullException rsfe) {
                        subRs.deleteRecord(subRmsId);
                        rsfe.printStackTrace();
                        return -1;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        String rmsName = this.getNewRmsName(); // 生成新的名字
        if (rmsName != null) {
            RecordStore subRs = null;
            try {
                subRs = RecordStore.openRecordStore(rmsName, true); // 创建新的rms
//                if (subRs.getSizeAvailable() < 30000) { // 防止频繁创建rms,但是却因为大小不足而写不进数据
//                    subRs.closeRecordStore();
//                    RecordStore.deleteRecordStore(rmsName);
//                    return -1;
//                }
                int subRmsId = subRs.addRecord(data, offset, len);
                si = new StoreItem(0, subRs.getName(), subRmsId, userData);
                ByteArrayOutputStream baos = new ByteArrayOutputStream(20);
                DataOutputStream dos = new DataOutputStream(baos);
                dos.writeUTF(si.subRmsName);
                dos.writeInt(si.subRmsId);
                dos.writeInt(si.userData);
                byte[] itemData = baos.toByteArray();
                try {
                    int rmsId = this.itemRs.addRecord(itemData, 0, itemData.length);
                    si.rmsId = rmsId;
                    this.subRms.put(rmsName, subRs);
                    this.idMap.put(new Integer(rmsId), si);
                    this.userDataMap.put(new Integer(userData), si);
                    return rmsId;
                } catch (RecordStoreFullException rsfe) {
                    subRs.closeRecordStore();
                    subRs = null;
                    RecordStore.deleteRecordStore(rmsName);
                    rsfe.printStackTrace();
                    return -1;
                }
            } catch (RecordStoreFullException rsfe) {
                try {
                    if (subRs != null) {
                        subRs.closeRecordStore();
                        RecordStore.deleteRecordStore(rmsName);
                        subRs = null;
                    }
                    rsfe.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return -1;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return -1;
    }
    public byte[] getRecordByUserData(int ud) {
        if (this.itemRs == null) {
            return null;
        }
        // 通过rmsId从itemRs中查找数据,然后通过读取的数据和idMap来找到真正的数据
        StoreItem si = (StoreItem)this.userDataMap.get(new Integer(ud));
        if (si != null) {
            RecordStore rs = (RecordStore)this.subRms.get(si.subRmsName);
            if (rs != null) {
                try {
                    return rs.getRecord(si.subRmsId);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
    public byte[] getRecord(int rmsId) {
        if (this.itemRs == null) {
            return null;
        }
        // 通过rmsId从idMap中查找索引,然后通过索引找到真正的数据
        StoreItem si = (StoreItem)this.idMap.get(new Integer(rmsId));
        if (si != null) {
            RecordStore rs = (RecordStore)this.subRms.get(si.subRmsName);
            if (rs != null) {
                try {
                    return rs.getRecord(si.subRmsId);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
    public boolean delRecordByUserData(int ud) {
        if (this.itemRs == null) {
            return false;
        }
        try {
            StoreItem si = (StoreItem)this.userDataMap.get(new Integer(ud));
            if (si != null) {
                RecordStore rs = (RecordStore)this.subRms.get(si.subRmsName);
                if (rs != null) {
                    try {
                        rs.deleteRecord(si.subRmsId);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                this.userDataMap.remove(new Integer(si.userData));
                this.idMap.remove(new Integer(si.subRmsId));
                this.itemRs.deleteRecord(si.rmsId);
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
    public boolean delRecord(int rmsId) {
        if (this.itemRs == null) {
            return false;
        }
        try {
            StoreItem si = (StoreItem)this.idMap.get(new Integer(rmsId));
            if (si != null) {
                RecordStore rs = (RecordStore)this.subRms.get(si.subRmsName);
                if (rs != null) {
                    try {
                        rs.deleteRecord(si.subRmsId);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                this.userDataMap.remove(new Integer(si.userData));
                this.idMap.remove(new Integer(rmsId));
                this.itemRs.deleteRecord(rmsId);
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
    public void close() {
        if (this.itemRs != null) {
            try {
                this.itemRs.closeRecordStore();
            } catch (Exception e) {
                e.printStackTrace();
            }
            Enumeration e = this.subRms.elements(); // 关闭所有的rms
            while (e.hasMoreElements()) {
                try {
                    RecordStore rs = (RecordStore) e.nextElement();
                    rs.closeRecordStore();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            this.subRms.clear();
            this.itemRs = null;
            this.idMap.clear();
            this.userDataMap.clear();
        }
    }
    private String getNewRmsName() {
        if (this.itemRs == null) {
            return null;
        }
        String baseName = null;
        try {
            baseName = this.itemRs.getName();
            String[] allRms = RecordStore.listRecordStores();
            int maxId = -1;
            for (int i = 0; i < allRms.length; i++) {
                if (allRms[i].startsWith("_" + baseName)) {
                    int id = Integer.parseInt(allRms[i].substring(baseName.length() + 1));
                    if (id > maxId) {
                        maxId = id;
                    }
                }
            }
            maxId++;
            return "_" + baseName + maxId;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
